﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using static WPF_Minesweeper.GameEnum;

namespace WPF_Minesweeper
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        #region 图片资源变量声明
        // 计时器、计数器图片变量声明
        private BitmapImage bmpTimer, bmpMiner;
        // 前景标记图片变量声明
        private BitmapImage bmpTag_1, bmpTag_2, bmpTag_3;
        // 数字图片变量声明
        private BitmapImage bmpSpace, bmpNum_1, bmpNum_2, bmpNum_3, bmpNum_4, bmpNum_5, bmpNum_6, bmpNum_7, bmpNum_8;
        // 地雷图片变量声明
        private BitmapImage bmpMine_1, bmpMine_2;
        // 爆炸图片变量声明
        private BitmapImage bmpBoom_1, bmpBoom_2, bmpBoom_3, bmpBoom_4, bmpBoom_5, bmpBoom_6;
        // 格子图片大小
        private System.Drawing.Size _cellSize = new System.Drawing.Size(35, 35);
        #endregion

        #region 主游戏数据变量
        // 底层背景数据（雷-1，0为空白，数值（1-8）周围雷数）
        private int[,] _backData = null;
        // 前景数据（1：正常盖住；2：红旗；3：问号）
        private int[,] _foreData = null;
        // 底层图片数组
        private Image[,] _backImage = null;
        // 前景图片数组
        private Image[,] _foreImage = null;
        // 游戏状态：未开始
        private GameState _gameState = GameState.None;
        // 随机数
        private Random rnd = new Random();
        // 游戏难度级别
        private GameLevel _gameLevel;
        public Level _level = Level.Primary;

        // 踩雷
        private Boom[] booms;
        // 地雷数量
        private int boomCount = 0;

        // 游戏过程计时器
        private System.Diagnostics.Stopwatch _stopWatchGame = new System.Diagnostics.Stopwatch();
        // 更新读秒文本框
        private DispatcherTimer _timerSetTimeText = new DispatcherTimer();
        // 用于胜利动画的计时器
        private DispatcherTimer _timerWinAnim = new DispatcherTimer();
        // 用于踩雷动画的计时器
        private DispatcherTimer _timerBoom = new DispatcherTimer();
        #endregion

        public MainWindow()
        {
            InitializeComponent();
            // 初始化图片资源
            GetImageResource();
            // 设置计时器、计数器图片
            SetTimerAndMineImage();
            // 初始化游戏计时器
            _timerSetTimeText.Interval = new TimeSpan(0, 0, 1);
            _timerSetTimeText.Tick += _timerSetTimeText_Tick;
            // 初始化动画计时器
            _timerWinAnim.Interval = new TimeSpan(0, 0, 0, 0, 300);
            _timerWinAnim.Tick += _timerWinAnim_Tick;
            // 初始化踩雷计时器
            _timerBoom.Interval = new TimeSpan(0, 0, 0, 0, 200);
            _timerBoom.Tick += _timerBoom_Tick;

            // 开始游戏
            ResetGame();
        }

        #region 游戏进程逻辑
        /// <summary>
        /// 重新开始游戏
        /// </summary>
        public void ResetGame()
        {
            // 初始化游戏状态、游戏数据
            InitialGameState();
            InitGameData(_level);
            // 初始化地雷计数器文本
            CounterText.Text = _gameLevel._mineNum.ToString();
            // 初始化计时器文本
            TimerText.Text = "0";
            // 设置地雷布置
            SetRndMine(_gameLevel._mineNum);
            // 设置底层格子周围地雷数值
            SetCellMineNumber();
            // 设置底层格子图片源
            SetBackCellImage();
            // 设置前景格子图片源
            SetForeCellImage();
            // 设置游戏状态
            _gameState = GameState.Start;
        }

        /// <summary>
        /// 判断游戏是否胜利
        /// </summary>
        private bool IsWin()
        {
            // 用以判断的变量
            bool flag = true;
            for (int y = 0; y < _gameLevel._colGrid; y++)
            {
                for (int x = 0; x < _gameLevel._rowGrid; x++)
                {
                    // 地雷未被红旗标记
                    if (_backData[y, x] == (int)BackState.Mine && _foreData[y, x] != (int)ForeState.Flag)
                    {
                        flag = false;
                        break;
                    }
                    // 存在未打开格子或标记为问号的格子
                    if (_foreData[y, x] == (int)ForeState.Normal || _foreData[y, x] == (int)ForeState.Question)
                    {
                        flag = false;
                        break;
                    }
                }

                if (!flag)
                    break;
            }
            // 返回游戏是否胜利
            return flag;
        }

        private int iCount;
        /// <summary>
        /// 游戏胜利处理逻辑
        /// </summary>
        private void WinProcess()
        {
            // 停止游戏计时
            _stopWatchGame.Stop();
            _timerSetTimeText.Stop();
            _gameState = GameState.None;
            // 重新覆盖格子的前景图片
            ForeCanvas.Children.Clear();
            for (int y = 0; y < _gameLevel._colGrid; y++)
            {
                for (int x = 0; x < _gameLevel._rowGrid; x++)
                {
                    _foreImage[y, x] = new Image();
                    _foreImage[y, x].Source = bmpTag_1;

                    _foreImage[y, x].Width = _cellSize.Width;
                    _foreImage[y, x].Height = _cellSize.Height;
                    _foreImage[y, x].SetValue(Canvas.LeftProperty, x * (double)_cellSize.Width);
                    _foreImage[y, x].SetValue(Canvas.TopProperty, y * (double)_cellSize.Height);
                    ForeCanvas.Children.Add(_foreImage[y, x]);
                }
            }
            // 动画行数
            iCount = _gameLevel._colGrid - 1;
            // 开启动画计时器
            _timerWinAnim.Start();
        }

        /// <summary>
        /// 踩雷动作
        /// </summary>
        private void FriedMines(int y, int x)
        {
            if (_backData[y, x] == (int)BackState.Mine)
            {
                // 设置踩中的地雷图片
                _backImage[y, x].Source = bmpMine_2;
            }
            // 爆炸图片数组
            BitmapSource[] tempImgSource = new BitmapSource[6];
            tempImgSource[0] = bmpBoom_1;
            tempImgSource[1] = bmpBoom_2;
            tempImgSource[2] = bmpBoom_3;
            tempImgSource[3] = bmpBoom_4;
            tempImgSource[4] = bmpBoom_5;
            tempImgSource[5] = bmpBoom_6;

            int bombCount = 0;
            // 遍历格子中隐藏的地雷
            for (int j = 0; j < _gameLevel._colGrid; j++)
            {
                for (int i = 0; i < _gameLevel._rowGrid; i++)
                {
                    // 播放爆炸效果
                    if (_backData[j, i] == (int)BackState.Mine && _foreData[j, i] != (int)ForeState.None
                        && ForeCanvas.Children.Contains(_foreImage[j, i]))
                    {
                        booms[bombCount++] = new Boom(ForeCanvas, j, i, tempImgSource);
                    }
                }
            }
            // 开启计时器
            _timerBoom.Start();
        }

        #endregion

        #region 游戏初始化设置
        /// <summary>
        /// 获取图片资源
        /// </summary>
        private void GetImageResource()
        {
            // 计时器、计数器图片
            bmpTimer = (BitmapImage)TryFindResource("ImgTimer");
            bmpMiner = (BitmapImage)TryFindResource("ImgMiner");
            // 前景标记图片
            bmpTag_1 = (BitmapImage)TryFindResource("ImgTag_1");
            bmpTag_2 = (BitmapImage)TryFindResource("ImgTag_2");
            bmpTag_3 = (BitmapImage)TryFindResource("ImgTag_3");
            // 数字图片
            bmpSpace = (BitmapImage)TryFindResource("ImgSpace");
            bmpNum_1 = (BitmapImage)TryFindResource("ImgNum_1");
            bmpNum_2 = (BitmapImage)TryFindResource("ImgNum_2");
            bmpNum_3 = (BitmapImage)TryFindResource("ImgNum_3");
            bmpNum_4 = (BitmapImage)TryFindResource("ImgNum_4");
            bmpNum_5 = (BitmapImage)TryFindResource("ImgNum_5");
            bmpNum_6 = (BitmapImage)TryFindResource("ImgNum_6");
            bmpNum_7 = (BitmapImage)TryFindResource("ImgNum_7");
            bmpNum_8 = (BitmapImage)TryFindResource("ImgNum_8");
            // 地雷图片
            bmpMine_1 = (BitmapImage)TryFindResource("ImgMine_1");
            bmpMine_2 = (BitmapImage)TryFindResource("ImgMine_2");
            // 爆炸图片
            bmpBoom_1 = (BitmapImage)TryFindResource("ImgBoom_1");
            bmpBoom_2 = (BitmapImage)TryFindResource("ImgBoom_2");
            bmpBoom_3 = (BitmapImage)TryFindResource("ImgBoom_3");
            bmpBoom_4 = (BitmapImage)TryFindResource("ImgBoom_4");
            bmpBoom_5 = (BitmapImage)TryFindResource("ImgBoom_5");
            bmpBoom_6 = (BitmapImage)TryFindResource("ImgBoom_6");
        }

        /// <summary>
        /// 设置计时器和计数器图片
        /// </summary>
        private void SetTimerAndMineImage()
        {
            ImgTimer.Source = bmpTimer;
            ImgCounter.Source = bmpMiner;
        }

        /// <summary>
        /// 初始化游戏状态
        /// </summary>
        private void InitialGameState()
        {
            // 停止各类计时器
            _timerSetTimeText.Stop();
            _timerWinAnim.Stop();

            _stopWatchGame.Reset();
            _stopWatchGame.Stop();
            _gameState = GameState.None;
        }

        // 游戏计时器事件
        private void _timerSetTimeText_Tick(object sender, EventArgs e)
        {
            TimerText.Text = ((int)_stopWatchGame.Elapsed.TotalSeconds + 1).ToString();
        }
        // 胜利动画计时器事件
        private void _timerWinAnim_Tick(object sender, EventArgs e)
        {
            // 判断动画行数
            if (iCount >= 0)
            {
                Storyboard sb1 = new Storyboard();
                DoubleAnimation daOpacity = null;

                for (int x = 0; x < _gameLevel._rowGrid; x++)
                {
                    if (_backData[iCount, x] == (int)BackState.Mine)
                    {
                        SetCellFore(x, iCount, ForeState.Flag);
                        continue;
                    }

                    daOpacity = new DoubleAnimation();
                    daOpacity.From = 1d;
                    daOpacity.To = 0d;
                    daOpacity.Duration = new Duration(TimeSpan.FromMilliseconds(600));

                    Storyboard.SetTarget(daOpacity, _foreImage[iCount, x]);
                    Storyboard.SetTargetProperty(daOpacity, new PropertyPath("(Image.Opacity)"));

                    sb1.Children.Add(daOpacity);
                }

                sb1.Begin();
                iCount--;
            }
            else
            {
                // 结束动画
                _timerWinAnim.Stop();
                // 设置结算窗体
                var Over = new OverWindows();
                Over.Owner = this;
                Over.Title = "游戏胜利";
                Over.OverTitleText.Text = "恭喜！您赢了！";
                Over.PlayTimeText.Text = "时间：" + TimerText.Text + " 秒";
                // 显示选项窗口
                Over.ShowDialog();
            }
        }
        // 踩雷动画计时器事件
        private void _timerBoom_Tick(object sender, EventArgs e)
        {
            booms[boomCount].DrawBoom();
            ForeCanvas.Children.Remove(_foreImage[booms[boomCount].GetPosition().X, booms[boomCount].GetPosition().Y]);
            boomCount++;

            if (boomCount == (booms.Length - 1))
            {
                boomCount = 0;
                // 停止计时器
                _timerBoom.Stop();
                // 设置计算窗体
                var Over = new OverWindows();
                Over.Owner = this;
                Over.Title = "游戏失败";
                Over.OverTitleText.Text = "不好意思，您输了。下次走运！";
                Over.PlayTimeText.Text = "时间：" + TimerText.Text + " 秒";
                // 显示选项窗口
                Over.ShowDialog();
            }
        }

        /// <summary>
        /// 初始化游戏数据
        /// </summary>
        /// <param name="level"> 难度级别 </param>
        private void InitGameData(Level level)
        {
            // 判断游戏难度级别
            switch (level)
            {
                // 初级
                case Level.Primary:
                    _gameLevel = new GameLevel(10, 9, 9);
                    _timerBoom.Interval = new TimeSpan(0, 0, 0, 0, 220);
                    break;
                // 中级
                case Level.Intermediate:
                    _gameLevel = new GameLevel(40, 16, 16);
                    _timerBoom.Interval = new TimeSpan(0, 0, 0, 0, 120);
                    break;
                // 高级
                case Level.Advanced:
                    _gameLevel = new GameLevel(99, 30, 16);
                    _timerBoom.Interval = new TimeSpan(0, 0, 0, 0, 50);
                    break;
            }
            // 设置窗口大小
            Width = _gameLevel._rowGrid * _cellSize.Width + 95;
            Height = _gameLevel._colGrid * _cellSize.Width + 145;
            // 获取屏幕大小
            double screenWidth = SystemParameters.WorkArea.Width;
            double screenHeight = SystemParameters.WorkArea.Height;
            // 使窗口居中
            Left = (screenWidth - Width) / 2;
            Top = (screenHeight - Height) / 2;
            // 设置前景、底层图块大小
            BackCanvas.Width = _gameLevel._rowGrid * _cellSize.Width;
            BackCanvas.Height = _gameLevel._colGrid * _cellSize.Height;
            ForeCanvas.Width = BackCanvas.Width;
            ForeCanvas.Height = BackCanvas.Height;
            // 初始化前景和背景数据
            _backData = new int[_gameLevel._colGrid, _gameLevel._rowGrid];
            _foreData = new int[_gameLevel._colGrid, _gameLevel._rowGrid];

            for (int y = 0; y < _gameLevel._colGrid; y++)
            {
                for (int x = 0; x < _gameLevel._rowGrid; x++)
                {
                    _backData[y, x] = (int)BackState.Blank;
                    _foreData[y, x] = (int)ForeState.Normal;
                }
            }
            // 初始化前景和背景图片数组
            _backImage = new Image[_gameLevel._colGrid, _gameLevel._rowGrid];
            _foreImage = new Image[_gameLevel._colGrid, _gameLevel._rowGrid];
            // 清理绘制区
            BackCanvas.Children.Clear();
            ForeCanvas.Children.Clear();

            // 地雷初始化
            booms = new Boom[_gameLevel._mineNum];
        }
        #endregion

        #region 游戏主体设置
        /// <summary>
        /// 随机布雷
        /// </summary>
        /// <param name="MineNum"> 地雷数量 </param>
        private void SetRndMine(int mineNum)
        {
            for (int k = 0; k < mineNum; k++)
            {
                int nullnum = 0;

                for (int j = 0; j < _gameLevel._colGrid; j++)
                {
                    for (int i = 0; i < _gameLevel._rowGrid; i++)
                    {
                        if (_backData[j, i] == (int)BackState.Blank)
                            nullnum++;
                    }
                }

                if (nullnum < 1)
                    return;

                int index = rnd.Next(1, nullnum);
                nullnum = 0;
                for (int j = 0; j < _gameLevel._colGrid; j++)
                {
                    for (int i = 0; i < _gameLevel._rowGrid; i++)
                    {
                        if (_backData[j, i] == 0)
                        {
                            nullnum++;
                            if (nullnum != index)
                                continue;
                            // 设置为地雷
                            _backData[j, i] = (int)BackState.Mine;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 设置周边地雷数值
        /// </summary>
        private void SetCellMineNumber()
        {
            // 遍历当前所有格子
            for (int y = 0; y < _gameLevel._colGrid; y++)
            {
                for (int x = 0; x < _gameLevel._rowGrid; x++)
                {
                    // 遇到地雷则将周围8个格子分别+1
                    if (_backData[y, x] == (int)BackState.Mine)
                    {
                        if (x - 1 > -1 && y - 1 > -1 && _backData[y - 1, x - 1] != (int)BackState.Mine)
                            _backData[y - 1, x - 1]++;

                        if (y - 1 > -1 && _backData[y - 1, x] != (int)BackState.Mine)
                            _backData[y - 1, x]++;

                        if (y - 1 > -1 && x + 1 < _gameLevel._rowGrid && _backData[y - 1, x + 1] != (int)BackState.Mine)
                            _backData[y - 1, x + 1]++;

                        if (x - 1 > -1 && _backData[y, x - 1] != (int)BackState.Mine)
                            _backData[y, x - 1]++;

                        if (x + 1 < _gameLevel._rowGrid && _backData[y, x + 1] != (int)BackState.Mine)
                            _backData[y, x + 1]++;

                        if (y + 1 < _gameLevel._colGrid && x - 1 > -1 && _backData[y + 1, x - 1] != (int)BackState.Mine)
                            _backData[y + 1, x - 1]++;

                        if (y + 1 < _gameLevel._colGrid && _backData[y + 1, x] != (int)BackState.Mine)
                            _backData[y + 1, x]++;

                        if (y + 1 < _gameLevel._colGrid && x + 1 < _gameLevel._rowGrid && _backData[y + 1, x + 1] != (int)BackState.Mine)
                            _backData[y + 1, x + 1]++;
                    }
                }
            }
        }

        /// <summary>
        /// 设置底层格子的图片源
        /// </summary>
        private void SetBackCellImage()
        {
            // 清空底层图块
            BackCanvas.Children.Clear();

            for (int y = 0; y < _gameLevel._colGrid; y++)
            {
                for (int x = 0; x < _gameLevel._rowGrid; x++)
                {
                    _backImage[y, x] = new Image();
                    if (_backData[y, x] == (int)BackState.Blank)
                    {
                        _backImage[y, x].Source = bmpSpace;
                    }
                    else if (_backData[y, x] == (int)BackState.Mine)
                    {
                        _backImage[y, x].Source = bmpMine_1;
                    }
                    else
                    {
                        switch (_backData[y, x])
                        {
                            case 1:
                                _backImage[y, x].Source = bmpNum_1;
                                break;
                            case 2:
                                _backImage[y, x].Source = bmpNum_2;
                                break;
                            case 3:
                                _backImage[y, x].Source = bmpNum_3;
                                break;
                            case 4:
                                _backImage[y, x].Source = bmpNum_4;
                                break;
                            case 5:
                                _backImage[y, x].Source = bmpNum_5;
                                break;
                            case 6:
                                _backImage[y, x].Source = bmpNum_6;
                                break;
                            case 7:
                                _backImage[y, x].Source = bmpNum_7;
                                break;
                            case 8:
                                _backImage[y, x].Source = bmpNum_8;
                                break;
                        }
                    }
                    _backImage[y, x].Width = _cellSize.Width;
                    _backImage[y, x].Height = _cellSize.Height;
                    _backImage[y, x].SetValue(Canvas.LeftProperty, x * (double)_cellSize.Width);
                    _backImage[y, x].SetValue(Canvas.TopProperty, y * (double)_cellSize.Height);
                    BackCanvas.Children.Add(_backImage[y, x]);
                }
            }
        }

        /// <summary>
        /// 设置前景格子图片源
        /// </summary>
        private void SetForeCellImage()
        {
            // 清除原有项
            ForeCanvas.Children.Clear();
            // 依次设置图片源
            for (int y = 0; y < _gameLevel._colGrid; y++)
            {
                for (int x = 0; x < _gameLevel._rowGrid; x++)
                {
                    if (_foreData[y, x] > (int)ForeState.None)
                    {
                        _foreImage[y, x] = new Image();
                        _foreImage[y, x].Source = bmpTag_1;

                        _foreImage[y, x].Width = _cellSize.Width;
                        _foreImage[y, x].Height = _cellSize.Height;
                        _foreImage[y, x].SetValue(Canvas.LeftProperty, x * (double)_cellSize.Width);
                        _foreImage[y, x].SetValue(Canvas.TopProperty, y * (double)_cellSize.Height);
                        ForeCanvas.Children.Add(_foreImage[y, x]);
                    }
                }
            }
        }
        #endregion

        #region 游戏鼠标响应逻辑
        /// <summary>
        /// 设置前景格子图样：地雷标记
        /// </summary>
        private void SetCellFore(int x, int y, ForeState state)
        {
            // 超出设定范围（安全防范）
            if (state > ForeState.Question || state < ForeState.None)
                return;
            // 判断当前格子的前景状态
            _foreData[y, x] = (int)state;
            // 移除当前格子的前景图片
            if (ForeCanvas.Children.Contains(_foreImage[y, x]))
                ForeCanvas.Children.Remove(_foreImage[y, x]);
            // 如果当前格子无前景覆盖
            if (state == ForeState.None)
                return;

            _foreImage[y, x].Source = bmpTag_2;
            ForeCanvas.Children.Add(_foreImage[y, x]);
        }

        /// <summary>
        /// 自动打开附近的空白区域
        /// </summary>
        private void OpenNearToSpace(int y, int x)
        {
            // 判断是否越界
            if (y < 0 || y >= _gameLevel._colGrid || x < 0 || x >= _gameLevel._rowGrid)
                return;

            if (_backData[y, x] == (int)BackState.Blank && _foreData[y, x] == (int)ForeState.Normal)
            {
                // 前景无覆盖：即已点开
                _foreData[y, x] = (int)ForeState.None;
                if (ForeCanvas.Children.Contains(_foreImage[y, x]))
                    ForeCanvas.Children.Remove(_foreImage[y, x]);
                // 依次遍历周边的格子
                if (y - 1 >= 0 && x - 1 >= 0)
                {
                    OpenNearToSpace(y - 1, x - 1);
                }

                if (y - 1 >= 0)
                {
                    OpenNearToSpace(y - 1, x);
                }

                if (y - 1 >= 0 && x + 1 <= _gameLevel._rowGrid - 1)
                {
                    OpenNearToSpace(y - 1, x + 1);
                }

                if (y + 1 <= _gameLevel._colGrid - 1 && x - 1 >= 0)
                {
                    OpenNearToSpace(y + 1, x - 1);
                }

                if (y + 1 <= _gameLevel._colGrid - 1)
                {
                    OpenNearToSpace(y + 1, x);
                }

                if (y + 1 <= _gameLevel._colGrid - 1 && x + 1 <= _gameLevel._rowGrid - 1)
                {
                    OpenNearToSpace(y + 1, x + 1);
                }
                if (x + 1 <= _gameLevel._rowGrid - 1)
                {
                    OpenNearToSpace(y, x + 1);
                }

                if (x - 1 >= 0)
                {
                    OpenNearToSpace(y, x - 1);
                }
                // 打开周围8个格子
                Open8Box(y, x);
            }
            return;
        }

        /// <summary>
        /// 打开周围的8个格子
        /// </summary>
        private void Open8Box(int y, int x)
        {
            if (y - 1 >= 0 && x - 1 >= 0)
            {
                _foreData[y - 1, x - 1] = (int)ForeState.None;
                if (ForeCanvas.Children.Contains(_foreImage[y - 1, x - 1]))
                    ForeCanvas.Children.Remove(_foreImage[y - 1, x - 1]);
            }
            if (y - 1 >= 0)
            {
                _foreData[y - 1, x] = (int)ForeState.None;
                if (ForeCanvas.Children.Contains(_foreImage[y - 1, x]))
                    ForeCanvas.Children.Remove(_foreImage[y - 1, x]);
            }
            if (y - 1 >= 0 && x + 1 <= _gameLevel._rowGrid - 1)
            {
                _foreData[y - 1, x + 1] = (int)ForeState.None;
                if (ForeCanvas.Children.Contains(_foreImage[y - 1, x + 1]))
                    ForeCanvas.Children.Remove(_foreImage[y - 1, x + 1]);
            }
            if (x - 1 >= 0)
            {
                _foreData[y, x - 1] = (int)ForeState.None;
                if (ForeCanvas.Children.Contains(_foreImage[y, x - 1]))
                    ForeCanvas.Children.Remove(_foreImage[y, x - 1]);
            }
            if (x + 1 <= _gameLevel._rowGrid - 1)
            {
                _foreData[y, x + 1] = (int)ForeState.None;
                if (ForeCanvas.Children.Contains(_foreImage[y, x + 1]))
                    ForeCanvas.Children.Remove(_foreImage[y, x + 1]);
            }
            if (y + 1 <= _gameLevel._colGrid - 1 && x - 1 >= 0)
            {
                _foreData[y + 1, x - 1] = (int)ForeState.None;
                if (ForeCanvas.Children.Contains(_foreImage[y + 1, x - 1]))
                    ForeCanvas.Children.Remove(_foreImage[y + 1, x - 1]);
            }
            if (y + 1 <= _gameLevel._colGrid - 1)
            {
                _foreData[y + 1, x] = (int)ForeState.None;
                if (ForeCanvas.Children.Contains(_foreImage[y + 1, x]))
                    ForeCanvas.Children.Remove(_foreImage[y + 1, x]);
            }
            if (y + 1 <= _gameLevel._colGrid - 1 && x + 1 <= _gameLevel._rowGrid - 1)
            {
                _foreData[y + 1, x + 1] = (int)ForeState.None;
                if (ForeCanvas.Children.Contains(_foreImage[y + 1, x + 1]))
                    ForeCanvas.Children.Remove(_foreImage[y + 1, x + 1]);
            }
        }

        /// <summary>
        /// 游戏前景图块鼠标左键点击
        /// </summary>
        private void ForeCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // 判断当前游戏状态
            if (_gameState == GameState.None)
                return;
            // 判断是否开始计时
            if (!_stopWatchGame.IsRunning && !_timerSetTimeText.IsEnabled)
            {
                TimerText.Text = "1";
                _stopWatchGame.Start();
                _timerSetTimeText.Start();
            }

            // 获取鼠标点击的格子位置
            Point mousePoint = e.MouseDevice.GetPosition(ForeCanvas);
            int dx = (int)(mousePoint.X / _cellSize.Width);
            int dy = (int)(mousePoint.Y / _cellSize.Height);
            // 判断是否是已打开的格子
            if (_foreData[dy, dx] == (int)ForeState.None)
                return;
            // 判断该格子的底层状态
            if (_backData[dy, dx] > (int)BackState.Blank)
            {
                if (ForeCanvas.Children.Contains(_foreImage[dy, dx]))
                {
                    ForeCanvas.Children.Remove(_foreImage[dy, dx]);
                    _foreData[dy, dx] = (int)ForeState.None;
                }
            }
            // 如果底层为空：打开周围空白格子
            if (_backData[dy, dx] == (int)BackState.Blank)
            {
                OpenNearToSpace(dy, dx);
            }
            // 如果底层为地雷：地雷爆炸
            if (_backData[dy, dx] == (int)BackState.Mine)
            {
                if (ForeCanvas.Children.Contains(_foreImage[dy, dx]))
                {
                    ForeCanvas.Children.Remove(_foreImage[dy, dx]);
                }

                FriedMines(dy, dx);
                // 设置游戏状态
                _gameState = GameState.None;
                // 停止游戏计时器
                _stopWatchGame.Stop();
            }

            // 判断是否胜利
            if (IsWin())
            {
                WinProcess();
            }
        }

        /// <summary>
        /// 游戏前景图块鼠标右键点击
        /// </summary>
        private void ForeCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            // 判断当前游戏状态
            if (_gameState == GameState.None)
                return;
            // 获取鼠标点击的格子位置
            Point mousePoint = e.MouseDevice.GetPosition(ForeCanvas);
            int dx = (int)(mousePoint.X / _cellSize.Width);
            int dy = (int)(mousePoint.Y / _cellSize.Height);
            // 判断是否是已打开的格子
            if (_foreData[dy, dx] == (int)ForeState.None)
                return;

            if (ForeCanvas.Children.Contains(_foreImage[dy, dx]))
            {
                // 循环前景数据
                _foreData[dy, dx]++;
                if (_foreData[dy, dx] > 3)
                {
                    _foreData[dy, dx] = 1;
                }
                // 设置相应的图片（原始、红旗、问号）
                if (_foreData[dy, dx] == (int)ForeState.Normal)
                    _foreImage[dy, dx].Source = bmpTag_1;
                else if (_foreData[dy, dx] == (int)ForeState.Flag)
                    _foreImage[dy, dx].Source = bmpTag_2;
                else if (_foreData[dy, dx] == (int)ForeState.Question)
                    _foreImage[dy, dx].Source = bmpTag_3;

                // 计算地雷数
                int num = 0;
                for (int y = 0; y < _gameLevel._colGrid; y++)
                {
                    for (int x = 0; x < _gameLevel._rowGrid; x++)
                    {
                        if (_foreData[y, x] == (int)ForeState.Flag)
                            num++;
                    }
                }
                // 更新计数器UI文本
                CounterText.Text = (_gameLevel._mineNum - num).ToString();
                // 胜利是否判断
                if (IsWin())
                {
                    WinProcess();
                }
            }
        }
        #endregion

        #region 游戏菜单选项点击事件
        /// <summary>
        /// 新游戏选项点击事件：开始新游戏
        /// </summary>
        private void MenuGameStart_Click(object sender, RoutedEventArgs e)
        {
            // 重新开始游戏
            ResetGame();
        }

        /// <summary>
        /// 菜单选项点击事件：打开选项窗口
        /// </summary>
        private void MenuOptions_Click(object sender, RoutedEventArgs e)
        {
            var win = new OptionsWindows();
            win.Owner = this;
            // 显示选项窗口
            win.ShowDialog();
        }

        /// <summary>
        /// 退出选项点击事件
        /// </summary>
        private void MenuGameExit_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }
        #endregion


    }


    /// <summary>
    /// 踩雷效果类
    /// </summary>
    public class Boom
    {
        Image boomImg = new Image();
        // 爆炸的图片数量
        const int FRAME_COUNT = 6;
        BitmapSource[] bmpSourceBoom = new BitmapSource[FRAME_COUNT];
        int currFrame = 0;
        DispatcherTimer timerBoom;
        Canvas _canvas = new Canvas();
        int dx, dy;

        public Boom(Canvas canvas, int dx, int dy, BitmapSource[] bmpImgBoom)
        {
            _canvas = canvas;
            this.dx = dx;
            this.dy = dy;
            bmpSourceBoom = bmpImgBoom;

            timerBoom = new DispatcherTimer();
            timerBoom.Interval = TimeSpan.FromMilliseconds(200);
            timerBoom.Tick += TimerBoom_Tick;
        }

        /// <summary>
        /// 爆炸动画计时器
        /// </summary>
        private void TimerBoom_Tick(object sender, EventArgs e)
        {
            boomImg.Source = bmpSourceBoom[currFrame];
            boomImg.Width = 35;
            boomImg.Height = 35;
            currFrame++;
            if (currFrame == 5)
            {
                currFrame = 0;
                if (_canvas.Children.Contains(boomImg))
                {
                    _canvas.Children.Remove(boomImg);
                }
                timerBoom.Stop();
            }
        }

        /// <summary>
        /// 绘制爆炸效果
        /// </summary>
        public void DrawBoom()
        {
            if (!_canvas.Children.Contains(boomImg))
                _canvas.Children.Add(boomImg);
            // 设置位置
            Canvas.SetLeft(boomImg, dy * 35);
            Canvas.SetTop(boomImg, dx * 35);
            // 开启计时器
            timerBoom.Start();
        }

        /// <summary>
        /// 获取格子的位置
        /// </summary>
        public System.Drawing.Point GetPosition()
        {
            return new System.Drawing.Point(dx, dy);
        }
    }

}
